from typing import List,Dict
from nicegui  import ui,events
from enums import OptionEnums
from disease_elements import DiseaseElement
from dataclass import QueryData,MedicalRecord,DRGRecord
from mrquery import MedicalRecordQuery
from drg_group.chs_drg_11.GroupProxy import GroupProxy
from drg_group.chs_drg_11.Base import GroupResult
from base import DRGCaculator



def input_date(bind_object:object,bind_property:str,label:str='开始日期',classname:str='w-40'):
    with ui.input(label=label).props('dense').classes(' '+classname+' ').bind_value(bind_object, bind_property) as input_date:
        with ui.menu().props('no-parent-event') as menu:
            with ui.date(on_change=menu.close).bind_value(input_date):
                with ui.row().classes('justify-end'):
                    ui.button('Close', on_click=menu.close).props('flat')
        with input_date.add_slot('append'):
            ui.icon('edit_calendar').on('click', menu.open).classes('cursor-pointer')



@ui.page('/grouper')
def grouper_main():
    query_data=QueryData()
    medical_record=MedicalRecord()
    drg_record=DRGRecord()

    def on_search_btn_click(qd:QueryData=None)->None:
        fields=['bah','xm','cybf','rysj','cybf','cysj']
        ret=MedicalRecordQuery(fields=fields,wheres=qd.to_string(),limit=1000)
        if  ret:
            table.update_rows(ret)

    def format_fields(records:List[Dict])->List[Dict]:
        '''
        格式化病案信息，分别将多个诊断和手术合并为一个字段
        :param records:病案信息列表
        '''
        # 遍历列表中的每个字典  
        for item in records:  
            # 创建一个新的列表，用于存放合并后的值  
            disease_merged_values = []  
            surgery_merged_values = []  
            # 定义需要合并的键[('编码字段','名称字段')]
            disease_to_merge=[('jbdm','zyzd'),('jbdm1','qtzd1'),('jbdm2','qtzd2'),('jbdm3','qtzd3'),('jbdm4','qtzd4'),('jbdm5','qtzd5'),('jbdm6','qtzd6'),('jbdm7','qtzd7'),('jbdm8','qtzd8'),('jbdm9','qtzd9'),('jbdm10','qtzd10')]  
            surgery_to_merge=[('ssjczbm1','ssjczmc1'),('ssjczbm2','ssjczmc2'),('ssjczbm3','ssjczmc3')]
            # 遍历需要合并的键  
            for key in disease_to_merge:  
                # 将对应键的值添加到新列表中  
                if item[key[0]] and len(item[key[0]])>6:  
                    disease_merged_values.append(item[key[0]]+" "+item[key[1]]) 
            for key in surgery_to_merge:  
                # 将对应键的值添加到新列表中 
                if item[key[0]] and len(item[key[0]])>6:   
                    surgery_merged_values.append(item[key[0]]+" "+item[key[1]])  
            # 在字典中添加新的键值对，键为'a'，值为合并后的列表  
            item['diseases'] = disease_merged_values  
            item['surgerys'] = surgery_merged_values  
            # 删除原来的键值对  
            for key in disease_to_merge:  
                del item[key[0]]   
                del item[key[1]]  
            for key in surgery_to_merge:  
                del item[key[0]]   
                del item[key[1]]  
            
            # 入出院时间由int转为str
            item['rysj']=str(item['rysj'])
            item['cysj']=str(item['cysj'])

        return records
    
    def search_with_patient_number(patient_number:str)->List[Dict]:
        '''
        根据住院号精确搜索病案信息
        :param patient_number:住院号
        '''
        if not patient_number:
            return
        ret=MedicalRecordQuery(wheres=f'bah="{patient_number}"',limit=1)
        if not ret:
            return
        return format_fields(ret)
    

    def update_medical_record(patient_number:str)->None:
        '''
        更新medical_record对象、更新诊断组件、更新手术组件的诊断和手术信息
        :param patient_number:
        '''
        ret=search_with_patient_number(patient_number)
        if not ret:
            return
        medical_record.from_dict(ret[0])
        disease.set_diseases(ret[0]['diseases'])
        disease_surgery.set_diseases(ret[0]['surgerys'])

    def on_table_row_click(e: events.GenericEventArguments)->None:  
        text=e.args['bah']
        update_medical_record(text)        

    def drg_group()->None:
        '''
            drg分组,调用分组接口、计算DRG值；更新drg_result计算drg病例点数、费用；显示分组结果
        '''
        medical_record.diseases=disease.get_diseases()
        medical_record.surgerys=disease_surgery.get_diseases()
        grouper=GroupProxy()
        # medical_record_string='22136028,2.0,50.0,18624.0,,13030501.0,16.0,1.0,"D61.900,E03.900,I10.x00x002","00.1801,00.1803"'
        group_result=grouper.group_record(medical_record.to_string())   # 调用分组接口
        print(group_result)
        if group_result.status=='无法入组':
            drg_info_box.classes('hidden',remove='inline')
            err_label.set_text(f'{group_result.status}：'+','.join([msg for msg in group_result.messages]))
            group_err_box.classes('inline',remove='hidden')
            return
        drg_record.from_drg_caculator(DRGCaculator(group_result,medical_record).drg_computed())   # 计算DRG值
        # 显示分组结果
        u_drg_code.set_text(f'DRG病组：{drg_record.drgs_code}  {drg_record.drgs_name}')
        u_drg_code.update()
        u_drg_weight.set_text(f'基础点数：{drg_record.drgs_weights}')
        u_drg_ratio.set_text(f'调整系数：{drg_record.drgs_ratio}')
        employee_gap=int(drg_record.drg_amount['employees']-drg_record.patient_amount)
        resident_gap=int(drg_record.drg_amount['resident']-drg_record.patient_amount)
        u_employee.set_text(f'职工医保DRG费用：'+str(drg_record.drg_amount['employees'])+f'元；   结算差额:{employee_gap} 元')
        u_resident.set_text(f'居民医保DRG费用：'+str(drg_record.drg_amount['resident'])+f'元；    结算差额:{resident_gap} 元')
        u_patient_type.set_text(f'病例类型：{drg_record.drg_type}')
        u_patient_weight.set_text(f'病例点数：{drg_record.patient_weights}')
        group_err_box.classes('hidden',remove='inline')
        drg_info_box.classes('inline',remove='hidden')




    with ui.row().style('gap:1px'):
        with ui.row().classes('w-full align-center border-b border-blue-500 pb-1'):
            ui.label('基本信息').classes('text-weight-bold text-blue-500 mx-4')
        with ui.row():
            input_patient_number=ui.input('住院号').classes('w-40').props('dense color="grey-3" ').bind_value(medical_record, 'patient_number').on('keydown.enter', lambda e: update_medical_record(medical_record.patient_number))
            with input_patient_number.add_slot('append'):
                ui.icon('search').props('color="orange"')
            m_patient_name=ui.input('患者姓名').classes('w-40').props('dense').bind_value(medical_record, 'patient_name')
            m_gender=ui.select({1:'男',2:'女'},label='性别').classes('w-40').props('dense').bind_value(medical_record, 'patient_gender')
            m_age=ui.number('年龄',format='%d',min=1,max=130,step=1).classes('w-40').props('dense').bind_value(medical_record, 'patient_age')
            m_department=ui.select(OptionEnums.DEPARTMENTS.value,label='(出院)科室').props('dense').classes('w-40').bind_value(medical_record, 'department')
        
        with ui.row():
            m_admission_date=input_date(label='入院日期',bind_object=medical_record,bind_property='admission_date')
            m_discharge_date=input_date(label='出院日期',bind_object=medical_record,bind_property='discharge_date')
            days=ui.number('住院天数',min=1,max=1000,step=1,format='%d').classes('w-40').props('dense').bind_value(medical_record, 'days')
            leaving_type=ui.select(OptionEnums.LEAVING_TYPES.value,label='离院方式').classes('w-40').props('dense').bind_value(medical_record, 'leaving_type')
            patient_amount=ui.number('住院费用',min=0,format='%.2f',suffix="元").props('dense').classes('w-40').bind_value(medical_record, 'patient_amount')

        with ui.column().classes('w-full mt-2').style('gap:2px;'):
            with ui.row(align_items='center').classes('h-10 border-b border-blue-500 w-full mb-2').style('gap:2px'):
                ui.label('诊断信息').classes('text-weight-bold text-blue-500 mx-4')
                ui.space()
                add_disease=ui.button('',icon='add_circle').props('dense').classes('outlined')
                up_btn=ui.button('',icon='arrow_back').props('dense')
                down_btn=ui.button('',icon='arrow_forward').props('dense')
                delete_btn=ui.button('',icon='delete').props('dense').classes('size-4')
            disease=DiseaseElement()
            add_disease.on_click(disease.add)
            up_btn.on_click(disease.move_pre)
            down_btn.on_click(disease.move_next)
            delete_btn.on_click(disease.delete)

        with ui.column().classes('w-full mt-2').style('gap:2px;'):
            with ui.row(align_items='center').classes('h-10 border-b border-blue-500 w-full mb-2').style('gap:2px'):
                ui.label('手术或操作').classes('text-weight-bold text-blue-500 mx-4')
                ui.space()
                # add_disease=ui.button('',icon='add_circle').props('dense').classes('outlined')
                pre_btn_surgery=ui.button('',icon='arrow_back').props('dense')
                next_btn_surgery=ui.button('',icon='arrow_forward').props('dense')
                delete_btn_surgery=ui.button('',icon='delete').props('dense').classes('size-4')
            disease_surgery=DiseaseElement(type='surgery')
            # add_disease.on_click(disease_surgery.add)
            pre_btn_surgery.on_click(disease_surgery.move_pre)
            next_btn_surgery.on_click(disease_surgery.move_next)
            delete_btn_surgery.on_click(disease_surgery.delete)

        with ui.column().classes('w-full mt-2').style('gap:2px;'):
            with ui.row(align_items='center').classes('h-10 border-b border-blue-500 w-full mb-2 items-center justify-center').style('gap:2px'):
                ui.button('DRG预分组',on_click=drg_group).props('color=secondary').classes('mb-4 w-40')

            with ui.row().classes('w-full'):
                with ui.row(align_items='start').classes('w-full hidden').style('gap:0px')  as drg_info_box:
                    # ui.label(f'DRG预分组结果').classes('text-weight-bold bg-sky-500 text-2xl text-white')
                    # with ui.splitter().classes('w-full') as splitter:
                    with ui.column().classes('w-1/2'):
                        with ui.row().style('gap:3px'):
                            ui.icon('auto_awesome_mosaic',size='sm',color='blue-6')
                            u_drg_code=ui.label(f'DRG病组：TS29 精神分裂症').classes('tracking-wide text-base text-blue-500')
                        with ui.row().style('gap:3px'):
                            ui.icon('arrow_right',size='sm',color='')
                            u_drg_weight=ui.label(f'基础点数：200').classes('tracking-wide text-slate-800 text-base')
                        with ui.row().style('gap:3px'):
                            ui.icon('arrow_right',size='sm',color='')
                            u_drg_ratio=ui.label(f'调整系数：1.0').classes('text-base text-slate-800 tracking-wider')
                    with ui.column().classes('w-1/2'):
                        with ui.row().style('gap:3px'):
                            ui.icon('currency_yen',size='sm',color='blue-6')
                            u_employee=ui.label(f'职工医保DRG费用：10000元; 差额：500').classes('tracking-wide text-base text-blue-500 ml-2')
                        with ui.row().style('gap:3px'):
                            ui.icon('currency_yen',size='sm',color='blue-6')
                            u_resident=ui.label(f'居民医保DRG费用：120000元; 差额：500').classes('tracking-wide text-base text-blue-500 ml-2')
                        with ui.row().style('gap:3px'):
                            ui.icon('arrow_right',size='sm',color='')
                            u_patient_type=ui.label(f'病例类型：正常病例').classes('text-base  text-slate-800 tracking-wider  ml-2')
                        with ui.row().style('gap:3px'):
                            ui.icon('arrow_right',size='sm',color='')
                            u_patient_weight=ui.label(f'病例点数：200').classes('text-base  text-slate-800 tracking-wider  ml-2')
            
                with ui.row().classes('w-full hidden') as group_err_box:
                    ui.icon('wrong_location',size='sm',color='red-6')
                    err_label=ui.label('')

    with ui.header(elevated=True).style('background-color: #3874c8').classes('items-center justify-between'):
        ui.label('达州市民康医院DRG预分组器').classes('text-h5')
        ui.button(on_click=lambda: left_drawer.toggle(), icon='menu').props('flat color=white')

    with ui.left_drawer(top_corner=False).props(' width=500').classes('border-r-2 border-blue-300') as left_drawer:
        with ui.column().classes('items-center justify-center border-t border-blue-500 w-full h-48').style('gap:2px'):
            with ui.row():
                inpatient_number=ui.input('住院号').props(' dense').classes('w-32').bind_value(query_data,'patient_number').on('keydown.enter', lambda :on_search_btn_click(query_data))
                patient_name=ui.input('患者姓名').props('dense').classes('w-32').bind_value(query_data,'patient_name').on('keydown.enter', lambda :on_search_btn_click(query_data))
                docter=ui.input('医生姓名').props(' dense').classes('w-32').bind_value(query_data,'docter_name').on('keydown.enter', lambda :on_search_btn_click(query_data))
                
            with ui.row():
                admission_date=input_date(label='起始日期',classname='w-32',bind_object=query_data,bind_property='start_date')
                discharge_date=input_date(label='截止日期',classname='w-32',bind_object=query_data,bind_property='end_date')
                leaving_status=ui.select(OptionEnums.LEAVING_STATUS.value,label='离院/在院',value='离院').props('dense').classes('w-32').bind_value(query_data,'leaving_type')

            with ui.row():
                department=ui.select(OptionEnums.DEPARTMENTS.value,label='(出院)科室',clearable=True).props('dense').classes('w-48').bind_value(query_data,'department')
                ui.element('div').classes('w-24')
                ui.element('div').classes('w-28')

            with ui.row():
                ui.button('查询', icon='search',on_click=lambda :on_search_btn_click(query_data)).props('dense').classes('w-32 mt-2')


        with ui.row().classes('w-full px-0 border-t border-blue-500 '):
            columns=[
                    {'name':'bah','label':'住院号','field': 'bah' },
                    {'name':'xm','label':'患者姓名','field': 'xm' },
                    {'name':'cybf','label':'科室','field': 'cybf' },
                    {'name':'rysj','label':'入院日期','field': 'rysj' },
                    {'name':'cysj','label':'出院日期','field': 'cysj' },
                    # {'label':'管床医师','field': 'docter' },
                ] 
            table = ui.table(columns=columns,rows=[], row_key='bah',pagination={'rowsPerPage':30,'page':1}).classes('w-full').props('flat ').style('height:calc(100vh - 290px)!important;')
            table.add_slot('header', r'''
                <q-tr :props="props">                    
                    <q-th v-for="col in props.cols" :key="col.name" :props="props">
                        {{ col.label }}
                    </q-th>
                </q-tr>
            ''')
            table.add_slot('body', r'''
                <q-tr :props="props" 
                    @click="() => $parent.$emit('row_selected', props.row)" 
                >                                
                    <q-td key="bah" :props="props" >  {{ props.row.bah }} </q-td>
                    <q-td key="xm" :props="props"> {{ props.row.xm }}  </q-td>
                    <q-td key="cybf" :props="props"> {{ props.row.cybf }}  </q-td>
                    <q-td key="rysj" :props="props"> {{ props.row.rysj }}  </q-td>
                    <q-td key="cysj" :props="props"> {{ props.row.cysj }}  </q-td>
                </q-tr>
            ''')
            table.on('row_selected', on_table_row_click)


    # with ui.right_drawer().style('background-color: #ebf1fa').props('bordered') as right_drawer:
    #     ui.label('RIGHT DRAWER')
    


ui.link('DRG预分组器', 'grouper')
# ui.link('ar-grid','ag-grid')
# ui.input('').classes('size-40').props('border type=textarea input-style={white-space: nowrap;line-height: 2.5;}')

ui.run(title='达州市民康医院DRG预分组器', port=8080)
